// SPDX-License-Identifier: GPL-2.0-only
/*
 * Based on mm/memblock.c
 *
 * Copyright (C) 1999 Ingo Molnar
 *               1999 Kanoj Sarcar, SGI
 *               2008 Johannes Weiner
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 * Author: Huawei OS Kernel Lab
 * Create: Thu Aug 15 16:14:23 2023
 * Access to this subsystem has to be serialized externally (which is true
 * for the boot process anyway).
 */

#include <linux/init.h>
#include <linux/pfn.h>
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/kmemleak.h>
#include <linux/range.h>
#include <linux/memblock.h>
#include <linux/bug.h>
#include <linux/io.h>

#include <asm/processor.h>

unsigned long max_pfn = -1;
unsigned long max_low_pfn = -1;

#define memblock_dbg(fmt, ...) pr_debug(fmt, ##__VA_ARGS__)

static void * __init memblock_alloc_internal(
		phys_addr_t size, phys_addr_t align,
		phys_addr_t min_addr, phys_addr_t max_addr,
		int nid, bool exact_nid)
{
	if (slab_is_available())
		return kzalloc(size, GFP_NOWAIT);
	return (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, get_order(size));
}

int memblock_free(phys_addr_t base, phys_addr_t size)
{
	phys_addr_t end = base + size - 1;

	pr_info("%s: [%pa-%pa] %pS\n", __func__, &base, &end, (void *)_RET_IP_);
	return 0;
}

void __memblock_free_late(phys_addr_t base, phys_addr_t size)
{
	phys_addr_t end = base + size - 1;

	pr_info("%s: [%pa-%pa] %pS\n", __func__, &base, &end, (void *)_RET_IP_);
}

phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start,
					phys_addr_t end, phys_addr_t size,
					phys_addr_t align)
{
	return 0;
}

void * __init memblock_alloc_try_nid_raw(
		phys_addr_t size, phys_addr_t align,
		phys_addr_t min_addr, phys_addr_t max_addr,
		int nid)
{
	void *ptr;

	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS\n",
			__func__, (u64)size, (u64)align, nid, &min_addr,
			&max_addr, (void *)_RET_IP_);

	ptr = memblock_alloc_internal(size, align,
			min_addr, max_addr, nid, false);
	if (ptr && size > 0)
		page_init_poison(ptr, size);

	return ptr;
}

void * __init memblock_alloc_try_nid(
		phys_addr_t size, phys_addr_t align,
		phys_addr_t min_addr, phys_addr_t max_addr,
		int nid)
{
	void *ptr;

	memblock_dbg("%s: %llu bytes align=0x%llx nid=%d from=%pa max_addr=%pa %pS\n",
			__func__, (u64)size, (u64)align, nid, &min_addr,
			&max_addr, (void *)_RET_IP_);
	ptr = memblock_alloc_internal(size, align,
			min_addr, max_addr, nid, false);
	if (ptr)
		memset(ptr, 0, size);

	return ptr;
}
